package se.sll.service.catalogue.export.restclient;

import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriBuilder;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.impl.client.DefaultHttpClient;
import org.jboss.resteasy.client.ClientRequest;
import org.jboss.resteasy.client.ClientRequestFactory;
import org.jboss.resteasy.client.core.executors.ApacheHttpClient4Executor;
import se.sll.service.catalogue.common.property.CatalogProperties;


/**
 * Helper class to call REST services
 * @author Jiri Uosukainen
 */
@Slf4j
public class RestClientHelper {
    
    /**
     * 
     * @param <T> The object returned
     * @param URL The 'GET' url, e.g. <code>http://localhost:8080/offers-1.0-SNAPSHOT/units/updatedafter/20130915150642</code>
     * @param returnType The type of the returned object
     * @return The object returned by the call to the REST service.
     * @throws Exception 
     */
    public static <T> T sendJSONGet(String URL, Class<T> returnType) throws Exception {
        log.info("RestClientHelper.sendJSONGet() Using URL: {}", URL);
              
        T entity = null;
        try {
            ClientRequestFactory crf = new ClientRequestFactory(UriBuilder.fromUri(URL).build());
            
            ClientRequest clientRequest = crf.createRelativeRequest("?");
            clientRequest.accept(MediaType.APPLICATION_JSON_TYPE);
            clientRequest.accept("application/json; charset=UTF-8");
            entity = clientRequest.getTarget(returnType);
            
        }
        catch (Exception e){
            log.error("CAUGHT EXCEPTION: {}", e.getClass().getName());
            log.error("EXCEPTION-MESSAGE IS: {}", e.getMessage());
            log.error("Failed URL: {}", URL);
            throw e;        
        }
        
        return entity; 
    }

    /**
     * 
     * @param <T> The object returned
     * @param URL The 'GET' url, e.g. <code>http://localhost:8080/offers-1.0-SNAPSHOT/units/updatedafter/20130915150642</code>
     * @param returnType The type of the returned object
     * @return The object returned by the call to the REST service.
     * @throws Exception 
     */
    public static <T> T sendJSONGetBA(String URL, Class<T> returnType) throws Exception {
        log.info("RestClientHelper.sendJSONGetBA() Using URL: {}", URL);
              
        T entity = null;
        DefaultHttpClient httpClient = new DefaultHttpClient();
        try {
            httpClient.getCredentialsProvider().setCredentials(
                    new AuthScope("localhost", 8080)
                    , new UsernamePasswordCredentials(
                            CatalogProperties.getProperty(CatalogProperties.NAME.SYSTEM_USER_USERNAME)
                            , CatalogProperties.getProperty(CatalogProperties.NAME.SYSTEM_USER_PASSWORD)));
            
            ApacheHttpClient4Executor executor = new ApacheHttpClient4Executor(httpClient);

            ClientRequestFactory crf = new ClientRequestFactory(executor, UriBuilder.fromUri(URL).build());
            
            ClientRequest clientRequest = crf.createRelativeRequest("?");
            clientRequest.accept(MediaType.APPLICATION_JSON_TYPE);
            clientRequest.accept("application/json; charset=UTF-8");
            entity = clientRequest.getTarget(returnType);
            
        }
        catch (Exception e){
            log.error("CAUGHT EXCEPTION: {}", e.getClass().getName());
            log.error("EXCEPTION-MESSAGE IS: {}", e.getMessage());
            log.error("Failed URL: {}", URL);
            throw e;        
        }
        finally{
            httpClient.getConnectionManager().shutdown();
        }
        
        return entity; 
    }    
    
    /**
     * Method to use for requests by post where the input is to large for using request parameters
     * @param <T> The object returned
     * @param URL  The 'POST' url, e.g. <code>http://localhost:8080/gui-1.0-SNAPSHOT/users/emails/</code>
     * @param body The request object
     * @param returnType The type of object returned by the call to the REST service.
     * @return
     * @throws Exception 
     */
    public static <T> T sendJSONPost(String URL, Object body, Class<T> returnType) throws Exception {
        log.info("RestClientHelper.sendJSONPost() Using URL: {}", URL);
        
        T entity = null;

        try {
            ClientRequestFactory crf = new ClientRequestFactory(UriBuilder.fromUri(URL).build());
            
            ClientRequest clientRequest = crf.createRelativeRequest("?");
            clientRequest.accept(MediaType.APPLICATION_JSON_TYPE);
            clientRequest.body(MediaType.APPLICATION_JSON_TYPE, body);
            
            entity = clientRequest.postTarget(returnType);
        } 
        catch (Exception e) {
            log.error("CAUGHT EXCEPTION: {}", e.getClass().getName());
            log.error("EXCEPTION-MESSAGE IS: {}", e.getMessage());
            log.error("Failed URL: {}", URL);
            throw e;
        }
        
        
        
        return entity;

    }    
    
    /**
     * Method to use for requests by post where the input is to large for using request parameters
     * @param <T> The object returned
     * @param URL  The 'POST' url, e.g. <code>http://localhost:8080/gui-1.0-SNAPSHOT/users/emails/</code>
     * @param body The request object
     * @param returnType The type of object returned by the call to the REST service.
     * @return
     * @throws Exception 
     */
    public static <T> T sendJSONPostBA(String URL, Object body, Class<T> returnType) throws Exception {
        log.info("RestClientHelper.sendJSONPostBA() Using URL: {}", URL);
        
        T entity = null;
        DefaultHttpClient httpClient = new DefaultHttpClient();
        try {
            httpClient.getCredentialsProvider().setCredentials(
                    new AuthScope("localhost", 8080)
                     , new UsernamePasswordCredentials(
                            CatalogProperties.getProperty(CatalogProperties.NAME.SYSTEM_USER_USERNAME)
                            , CatalogProperties.getProperty(CatalogProperties.NAME.SYSTEM_USER_PASSWORD)));
           ApacheHttpClient4Executor executor = new ApacheHttpClient4Executor(httpClient);    
            
            ClientRequestFactory crf = new ClientRequestFactory(executor, UriBuilder.fromUri(URL).build());
            ClientRequest clientRequest = crf.createRelativeRequest("?");           
            clientRequest.accept(MediaType.APPLICATION_JSON_TYPE);
            clientRequest.body(MediaType.APPLICATION_JSON_TYPE, body);
            
            entity = clientRequest.postTarget(returnType);
        } 
        catch (Exception e) {
            log.error("CAUGHT EXCEPTION: {}", e.getClass().getName());
            log.error("EXCEPTION-MESSAGE IS: {}", e.getMessage());
            log.error("Failed URL: {}", URL);
            throw e;
        }
        finally{
            httpClient.getConnectionManager().shutdown();
        }
        
        return entity;

    }
    
// Method using resteasy client (not used since not present in JBoss EAP 6.3.0)    
// public static <T> T sendJSONPost2(String url, Object body, Class<T> returnType) throws Exception {
//        log.info("RestClientHelper.sendJSONPost2() Using URL: {}", url);
//        return ClientBuilder.newClient()
//                .register(new Authenticator("super", "super"))
//                .target(url).request()
//                .accept(MediaType.APPLICATION_JSON_TYPE)
//                .header("Content-Type", MediaType.APPLICATION_JSON)
//                .post(Entity.entity(body, MediaType.APPLICATION_JSON_TYPE), returnType);
//    }
    
    
}
